////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                            //
//                                                         WNProject                                                          //
//                                                                                                                            //
//            This file is distributed under the BSD 2-Clause open source license. See License.txt for details.               //
//                                                                                                                            //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef __WN_PLANE_H__
#define __WN_PLANE_H__

#include "WNCore/inc/WNBase.h"

namespace WNMath {
    class WNPoint3;
    class WNVector3;

    class WNPlane {
    public:
        WNPlane();
        explicit WNPlane(const WN_FLOAT32* _f);
        explicit WNPlane(const WNVector3& _normal, WN_FLOAT32 _distance);
        explicit WNPlane(WN_FLOAT32 _a, WN_FLOAT32 _b, WN_FLOAT32 _c, WN_FLOAT32 _d);

        operator WN_FLOAT32* ();
        operator const WN_FLOAT32* () const;

        WNPlane& operator += (const WNPlane& _plane);
        WNPlane& operator -= (const WNPlane& _plane);

        WNPlane operator + () const;
        WNPlane operator - () const;

        WNPlane operator + (const WNPlane& _plane) const;
        WNPlane operator - (const WNPlane& _plane) const;

        WN_BOOL operator == (const WNPlane& _plane) const;
        WN_BOOL operator != (const WNPlane& _plane) const;

        WN_VOID Zero();
        WN_VOID Define(const WNPoint3& _point1, const WNPoint3& _point2, const WNPoint3& _point3);
        WN_VOID Define(const WNVector3& _vector1, const WNVector3& _vector2, const WNVector3& _vector3);
        WN_VOID Normalize();
        WN_VOID Translate(const WNVector3& _translation);

        WNVector3 Normal() const;
        WN_FLOAT32 Distance() const;

        WN_BOOL IsZero() const;

        WN_VOID Set(const WN_FLOAT32* _f);
        WN_VOID Set(WN_FLOAT32 _a, WN_FLOAT32 _b, WN_FLOAT32 _c, WN_FLOAT32 _d);

        WNPlane GetNormalized() const;
        WNPlane GetTranslated(const WNVector3& _translation) const;

    public:
        union {
            struct {
                WN_FLOAT32 a;
                WN_FLOAT32 b;
                WN_FLOAT32 c;
                WN_FLOAT32 d;
            };

            WN_FLOAT32 raw[4];
        };
    };
}

#endif // __WN_PLANE_H__